﻿using IdentityServer4;
using IdentityServer4.Models;

namespace IdsDemo
{
    public class Config
    {
        //public static IEnumerable<IdentityResource> GetIdentityResources()
        //{
        //    return new List<IdentityResource>
        //    {
        //        new IdentityResource(
        //            name: "profile",
        //            userClaims: new[] { "name", "email", "website" },
        //            displayName: "您的个人资料数据")
        //    };
        //}

        /// <summary>
        /// 自定义身份资源
        /// 修改 Config.cs 中的 IdentityResources 属性，添加对标准 openid （subject id）和 profile （名字、姓氏等）范围的支持
        /// </summary>
        public static IEnumerable<IdentityResource> IdentityResources =>
            new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email(),
                new IdentityResources.Address(),
            };
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("invoice", "发票 API")
                {
                    Scopes = { "invoice.read", "invoice.pay", "manage" }
                },

                new ApiResource("customer", "客户 API")
                {
                    Scopes = { "customer.read", "customer.contact", "manage" }
                },

                new ApiResource("rescource_api1","My API_1")
                {
                    Scopes = new List<string>{ "api1" }
                },
                //客户端模式
                new ApiResource("clientDemo", "Demo API")
                {
                    ApiSecrets = { new Secret("secret".Sha256()) },

                    Scopes = { "clientScope", "api.scope1", "api.scope2" }
                }
            };
        }
        public static IEnumerable<ApiScope> ApiScopes =>
            new List<ApiScope>
            {
                //ApiScope name 值为ApiResource中Scopes值
                new ApiScope("clientScope", "My API-1"),
                new ApiScope("api2", "My Api2"),
                new ApiScope(name: "read",   displayName: "读取您的数据。"),
                new ApiScope(name: "write",  displayName: "写入您的数据。"),
                new ApiScope(name: "delete", displayName: "删除您的数据。"),
                // 发票 API 特有的 scopes
                new ApiScope(name: "invoice.read",   displayName: "读取您的发票。"),
                new ApiScope(name: "invoice.pay",    displayName: "支付您的发票。"),

                // 客户 API 特有的 scopes
                new ApiScope(name: "customer.read",    displayName: "读取您的客户信息。"),
                new ApiScope(name: "customer.contact", displayName: "允许联系您的客户之一。"),

                // 共享 scope
                new ApiScope(name: "manage", displayName: "提供对发票和客户数据的管理访问。")
            };

        /// <summary>
        /// 定义资源后，您可以通过 AllowedScopes 选项（省略其他属性）将其访问权限授予客户端:
        /// 然后客户端可以使用 scope 参数请求资源https://demo.identityserver.io/connect/authorize?client_id=client&scope=openid profile
        /// </summary>
        public static IEnumerable<Client> Clients =>
            new List<Client>
            {
                // 机器到机器客户端（来自快速入门 1 开始）
                new Client
                {
                    ClientId = "client",
                    // 用于身份验证的密钥
                    ClientSecrets = { new Secret("secret".Sha256()) },
                    // 没有交互式用户，使用 clientid/secret 进行身份验证
                    AllowedGrantTypes = GrantTypes.ClientCredentials, //客户端模式
                    // 客户端有权访问的范围--ApiScope的Scope
                    AllowedScopes = { "clientScope" }
                },
                // 交互式 ASP.NET Core MVC 客户端
                new Client
                {
                    ClientId = "mvc",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.Code,

                    // 登录后重定向到哪里
                    RedirectUris = { "https://localhost:5002/signin-oidc" },

                    // 注销后重定向到哪里
                    PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
                    //我们通过 AllowOfflineAccess 属性启用对刷新令牌的支持
                    AllowOfflineAccess = true,
                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api1"
                    }
                },

                 new Client
                {
                    ClientId = "client_2",

                    AllowedScopes = { "openid", "profile" }
                },
                 //var interactiveClient = 
                new Client
                {
                    ClientId = "interactive",

                    AllowedGrantTypes = GrantTypes.Code,
                    AllowOfflineAccess = true,
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    RedirectUris =           { "http://localhost:5002/signin-oidc" },
                    PostLogoutRedirectUris = { "http://localhost:5002/" },
                    FrontChannelLogoutUri =    "http://localhost:5002/signout-oidc",

                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,

                        "api1", "api2.read_only"
                    },
                },
                new Client
                {
                    ClientId = "client_api2",
                    // 要使用RefreshToken时，必须要把AllowedGrantTypes设置为授权代码、混合和资源所有者密码凭证流
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, //GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256()) //secret加密密钥 Sha256加密方式
                    },
                    AllowedScopes =
                    {
                        "api2",
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                    },
                    // 刷新Token时RefreshToken保持不变
                    RefreshTokenUsage = TokenUsage.ReUse,
                    RefreshTokenExpiration = TokenExpiration.Sliding,
                    // RefreshToken过期时间
                    SlidingRefreshTokenLifetime = 3600,
                    // 明确授权请求刷新令牌
                    AllowOfflineAccess = true,
                    // TOken过期时间
                    AccessTokenLifetime = 60,
                },

                #region IdentityServer4-demo

                // non-interactive
                new Client
                {
                    ClientId = "m2m",
                    ClientName = "Machine to machine (client credentials)",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    AllowedScopes = { "api", "api.scope1", "api.scope2", "scope2", "policyserver.runtime", "policyserver.management" },
                },
                new Client
                {
                    ClientId = "m2m.short",
                    ClientName = "Machine to machine with short access token lifetime (client credentials)",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    AllowedScopes = { "api", "api.scope1", "api.scope2", "scope2" },
                    AccessTokenLifetime = 75
                },

                // interactive
                new Client
                {
                    ClientId = "interactive.confidential",
                    ClientName = "Interactive client (Code with PKCE)",

                    RedirectUris = { "https://notused" },
                    PostLogoutRedirectUris = { "https://notused" },

                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
                    AllowedScopes = { "openid", "profile", "email", "api", "api.scope1", "api.scope2", "scope2" },

                    AllowOfflineAccess = true,
                    RefreshTokenUsage = TokenUsage.ReUse,
                    RefreshTokenExpiration = TokenExpiration.Sliding
                },
                new Client
                {
                    ClientId = "interactive.confidential.hybrid",
                    ClientName = "Interactive client (OIDC Hybrid Flow)",

                    RedirectUris = { "https://notused" },
                    PostLogoutRedirectUris = { "https://notused" },

                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                    AllowedScopes = { "openid", "profile", "email", "api", "api.scope1", "api.scope2", "scope2" },

                    AllowOfflineAccess = true,
                    RefreshTokenUsage = TokenUsage.ReUse,
                    RefreshTokenExpiration = TokenExpiration.Sliding
                },
                new Client
                {
                    ClientId = "interactive.confidential.short",
                    ClientName = "Interactive client with short token lifetime (Code with PKCE)",

                    RedirectUris = { "https://notused" },
                    PostLogoutRedirectUris = { "https://notused" },

                    ClientSecrets = { new Secret("secret".Sha256()) },
                    RequireConsent = false,

                    AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
                    RequirePkce = true,
                    AllowedScopes = { "openid", "profile", "email", "api", "api.scope1", "api.scope2", "scope2" },

                    AllowOfflineAccess = true,
                    RefreshTokenUsage = TokenUsage.ReUse,
                    RefreshTokenExpiration = TokenExpiration.Sliding,

                    AccessTokenLifetime = 75
                },

                new Client
                {
                    ClientId = "interactive.public",
                    ClientName = "Interactive client (Code with PKCE)",

                    RedirectUris = { "https://notused" },
                    PostLogoutRedirectUris = { "https://notused" },

                    RequireClientSecret = false,

                    AllowedGrantTypes = GrantTypes.Code,
                    AllowedScopes = { "openid", "profile", "email", "api", "api.scope1", "api.scope2", "scope2" },

                    AllowOfflineAccess = true,
                    RefreshTokenUsage = TokenUsage.OneTimeOnly,
                    RefreshTokenExpiration = TokenExpiration.Sliding
                },
                new Client
                {
                    ClientId = "interactive.public.short",
                    ClientName = "Interactive client with short token lifetime (Code with PKCE)",

                    RedirectUris = { "https://notused" },
                    PostLogoutRedirectUris = { "https://notused" },

                    RequireClientSecret = false,

                    AllowedGrantTypes = GrantTypes.Code,
                    AllowedScopes = { "openid", "profile", "email", "api", "api.scope1", "api.scope2", "scope2" },

                    AllowOfflineAccess = true,
                    RefreshTokenUsage = TokenUsage.OneTimeOnly,
                    RefreshTokenExpiration = TokenExpiration.Sliding,

                    AccessTokenLifetime = 75
                },

                new Client
                {
                    ClientId = "device",
                    ClientName = "Device Flow Client",

                    AllowedGrantTypes = GrantTypes.DeviceFlow,
                    RequireClientSecret = false,

                    AllowOfflineAccess = true,
                    RefreshTokenUsage = TokenUsage.OneTimeOnly,
                    RefreshTokenExpiration = TokenExpiration.Sliding,

                    AllowedScopes = { "openid", "profile", "email", "api", "api.scope1", "api.scope2", "scope2" }
                },
                
                // oidc login only
                new Client
                {
                    ClientId = "login",

                    RedirectUris = { "https://notused" },
                    PostLogoutRedirectUris = { "https://notused" },

                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowedScopes = { "openid", "profile", "email" },
                },

                new Client
                {
                    ClientId = "hybrid",
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedGrantTypes = GrantTypes.Hybrid,
                    RequirePkce = false,

                    RedirectUris = { "https://notused" },
                    PostLogoutRedirectUris = { "https://notused" },

                    AllowOfflineAccess = true,
                    AllowedScopes = { "openid", "profile", "email", "api", "api.scope1", "api.scope2", "scope2" }
                }

	            #endregion


            };


        public static IEnumerable<ApiScope> GetScope()
        {
            return new ApiScope[] {
                new ApiScope("scope1"),
                new ApiScope("scope2"),
            };

        }

    }
}
